#include "rknntool.h"
#include <opencv2/opencv.hpp>
#include "qglobal.h"
#include "rknn_api.h"
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

void print_fp16_value(fp16_t *address)
{
    // 创建一个cv::Mat对象来存储FP16值
    cv::Mat fp16_mat(1, 1, CV_16FC1, address);

    // 将FP16值转换为float
    cv::Mat float_mat;
    fp16_mat.convertTo(float_mat, CV_32F);

    // 读取转换后的float值
    float value = float_mat.at<float>(0, 0);

    std::cout << "FP16 value converted to float: " << value << std::endl;
}
void save_image(const float* data, int width, int height, const std::string& filename) {
    // 创建一个 float 类型的 Mat
    cv::Mat float_image(height, width, CV_32F, const_cast<float*>(data));

    // 找到最小值和最大值
    double min_val, max_val;
    cv::minMaxLoc(float_image, &min_val, &max_val);

    // 映射到 [0, 255]
    cv::Mat normalized_image;
    float_image.convertTo(normalized_image, CV_8U, 255.0 / (max_val - min_val), -min_val * 255.0 / (max_val - min_val));

    // 保存图像
    cv::imwrite(filename, normalized_image);
}
int64_t getCurrentTimeUs()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000 + tv.tv_usec;
}

int rknn_GetTopN(float *pfProb, float *pfMaxProb, uint32_t *pMaxClass, uint32_t outputCount, uint32_t topNum)
{
    uint32_t i, j;
    uint32_t top_count = outputCount > topNum ? topNum : outputCount;

    for (i = 0; i < topNum; ++i)
    {
        pfMaxProb[i] = -FLT_MAX;
        pMaxClass[i] = -1;
    }

    for (j = 0; j < top_count; j++)
    {
        for (i = 0; i < outputCount; i++)
        {
            if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || (i == *(pMaxClass + 3)) ||
                (i == *(pMaxClass + 4)))
            {
                continue;
            }

            if (pfProb[i] > *(pfMaxProb + j))
            {
                *(pfMaxProb + j) = pfProb[i];
                *(pMaxClass + j) = i;
            }
        }
    }

    return 1;
}

void dump_tensor_attr(rknn_tensor_attr *attr)
{
    qInfo("  index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, "
           "zp=%d, scale=%f\n",
           attr->index, attr->name, attr->n_dims, attr->dims[0], attr->dims[1], attr->dims[2], attr->dims[3],
           attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type),
           get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
}

unsigned char *load_model(const char *filename, int *model_size)
{
    FILE *fp = fopen(filename, "rb");
    if (fp == nullptr)
    {
        printf("fopen %s fail!\n", filename);
        return NULL;
    }
    fseek(fp, 0, SEEK_END);
    int model_len = ftell(fp);
    unsigned char *model = (unsigned char *)malloc(model_len);
    fseek(fp, 0, SEEK_SET);
    if (model_len != fread(model, 1, model_len, fp))
    {
        printf("fread %s fail!\n", filename);
        free(model);
        return NULL;
    }
    *model_size = model_len;
    if (fp)
    {
        fclose(fp);
    }
    return model;
}
